import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart' as getx;
import 'package:yqmssa_app/config/app_config.dart';
import 'package:yqmssa_app/config/get_devide_info.dart';
import 'package:yqmssa_app/router/page_router.dart';
import 'package:yqmssa_app/utils/shared_utils.dart';

import 'http_path.dart';

enum ReqType { get, post, delete, put, request }

class MyRequest {
  static MyRequest get _http => MyRequest._internal();

  factory MyRequest() => _http;

  late Dio _dio;

  MyRequest._internal() {
    final options = BaseOptions(baseUrl: HttpPath.appUrl, headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/x-www-form-urlencoded',
      "appVersion": AppConfig.version,
    });
    // 初始化dio
    _dio = Dio(options);
    // 添加拦截器bui
    _dio.interceptors.add(InterceptorsWrapper(onRequest: _onRequest, onResponse: _onResponse, onError: _onError));

    if (false) {
      _dio.httpClientAdapter = IOHttpClientAdapter(onHttpClientCreate: ((client) {
        client.findProxy = (url) {
          return 'PROXY 192.168.55.136:8888';
        };
        client.badCertificateCallback = (X509Certificate cert, stringHost, int port) => true; //忽略证书
        return client;
      }));
    }
  }

  /// 请求拦截器
  _onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    if (options.data is Map) {
      if (sharedUtils.token.isNotEmpty) options.data["token"] = sharedUtils.token;
      if ([HttpPath.appJh, HttpPath.appLogin].contains(options.path)) {
        final device = await GetDeviceInfo.getVersion();
        final brand = await GetDeviceInfo.getBrand();
        final androidVersion = await GetDeviceInfo.getAndroidVersion();
        options.data["device"] = device;
        options.data["brand"] = brand;
        options.data["androidVersion"] = androidVersion;
      }
      options.data["app_bundle_label"] = AppConfig.appBundleLabel;
      options.data["pkg"] = AppConfig.packageName;
      options.data["channel"] = AppConfig.channel;
    }

    // 更多业务需求
    handler.next(options);
  }

  /// 相应拦截器
  _onResponse(Response response, ResponseInterceptorHandler handler) async {
    // 请求成功是对数据做基本处理
    if (response.statusCode == 200) {
      if (response.data["code"] != 1 && response.data["code"] != 200) {
        if (response.data["code"] == 501) {
          getx.Get.offAllNamed(PageRouter.login);
        } else {
          SmartDialog.showToast(response.data["msg"] ?? "请求失败", alignment: Alignment.center);
          debugPrint("请求路径🚀🚀：${response.requestOptions.path}\n错误码🚀🚀：${response.data["code"]}\n错误信息🚀🚀：${response.data["msg"] ?? "未知错误"}");
          handler.reject(
            DioException(
              requestOptions: response.requestOptions,
              response: response,
              message: [HttpPath.signUp].contains(response.requestOptions.path)
                  ? response.data["msg"]
                  : "请求路径🚀🚀：${response.requestOptions.path}\n错误码🚀🚀：${response.data["code"]}\n错误信息🚀🚀：${response.data["msg"] ?? "未知错误"}",
            ),
          );
        }
      } else {
        handler.next(response);
      }
    } else {
      debugPrint("请求路径🚀：${response.requestOptions.path}\n错误码🚀：${response.statusCode}\n错误信息🚀：${response.statusMessage}");
      handler.reject(
        DioException(
          requestOptions: response.requestOptions,
          response: response,
          message: "请求路径🚀：${response.requestOptions.path}\n错误码🚀：${response.statusCode}\n错误信息🚀：${response.statusMessage}",
        ),
      );
    }
  }

  /// 错误处理
  _onError(DioError error, ErrorInterceptorHandler handler) {
    debugPrint("请求路径🚀🚀🚀：${error.requestOptions.path}\n错误码🚀🚀🚀：${error.type.toString()}\n错误信息🚀🚀🚀：${error.message}");
    switch (error.type) {
      case DioExceptionType.connectionError:
        handler.reject(DioException(requestOptions: error.requestOptions, response: error.response, message: error.message));
        break;
      case DioExceptionType.badResponse:
        handler.reject(DioException(requestOptions: error.requestOptions, response: error.response, message: error.message));
        break;
      case DioExceptionType.cancel:
        handler.reject(DioException(requestOptions: error.requestOptions, response: error.response, message: error.message));
        break;
      case DioExceptionType.connectionTimeout:
        handler.reject(DioException(requestOptions: error.requestOptions, response: error.response, message: error.message));
        break;
      case DioExceptionType.receiveTimeout:
        handler.reject(DioException(requestOptions: error.requestOptions, response: error.response, message: error.message));
        break;
      case DioExceptionType.sendTimeout:
        handler.reject(DioException(requestOptions: error.requestOptions, response: error.response, message: error.message));
        break;
      case DioExceptionType.unknown:
        handler.reject(DioException(requestOptions: error.requestOptions, response: error.response, message: error.message));
        break;
      default:
        handler.next(error);
    }
  }

  Future dioReq(
    String path, {
    ReqType method = ReqType.post,
    data,
    Map<String, dynamic>? params,
    CancelToken? cancelToken,
    Options? options,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    const methodValues = {
      ReqType.get: 'get',
      ReqType.post: 'post',
      ReqType.put: 'put',
      ReqType.delete: 'delete',
      ReqType.request: 'request',
    };
    options ??= Options(method: methodValues[method]);
    final response = await _dio.request(
      path,
      data: data ?? {},
      options: options,
      queryParameters: params,
      cancelToken: cancelToken,
      onReceiveProgress: onReceiveProgress,
      onSendProgress: onSendProgress,
    );
    return response.data;
  }
}
